home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Delphi Anthology
/
aDELPHI.iso
/
Runimage
/
Delphi50
/
Source
/
Property Editors
/
fldlinks.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1999-08-11
|
15KB
|
537 lines
{*******************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ Master/Detail Field Links Editor }
{ }
{ Copyright (c) 1997,99 Inprise Corporation }
{ }
{*******************************************************}
unit Fldlinks;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms,
StdCtrls, ExtCtrls, DB, Buttons, DsgnIntf;
type
{ TFieldLink }
TFieldLinkProperty = class(TStringProperty)
private
FChanged: Boolean;
FDataSet: TDataSet;
protected
function GetDataSet: TDataSet;
procedure GetFieldNamesForIndex(List: TStrings); virtual;
function GetIndexBased: Boolean; virtual;
function GetIndexDefs: TIndexDefs; virtual;
function GetIndexFieldNames: string; virtual;
function GetIndexName: string; virtual;
function GetMasterFields: string; virtual; abstract;
procedure SetIndexFieldNames(const Value: string); virtual;
procedure SetIndexName(const Value: string); virtual;
procedure SetMasterFields(const Value: string); virtual; abstract;
public
constructor CreateWith(ADataSet: TDataSet); virtual;
procedure GetIndexNames(List: TStrings);
property IndexBased: Boolean read GetIndexBased;
property IndexDefs: TIndexDefs read GetIndexDefs;
property IndexFieldNames: string read GetIndexFieldNames write SetIndexFieldNames;
property IndexName: string read GetIndexName write SetIndexName;
property MasterFields: string read GetMasterFields write SetMasterFields;
property Changed: Boolean read FChanged;
procedure Edit; override;
function GetAttributes: TPropertyAttributes; override;
property DataSet: TDataSet read GetDataSet;
end;
{ TLink Fields }
TLinkFields = class(TForm)
DetailList: TListBox;
MasterList: TListBox;
BindList: TListBox;
Label30: TLabel;
Label31: TLabel;
IndexList: TComboBox;
IndexLabel: TLabel;
Label2: TLabel;
Bevel1: TBevel;
Bevel2: TBevel;
AddButton: TButton;
DeleteButton: TButton;
ClearButton: TButton;
Button1: TButton;
Button2: TButton;
Help: TButton;
procedure FormCreate(Sender: TObject);
procedure BindingListClick(Sender: TObject);
procedure AddButtonClick(Sender: TObject);
procedure DeleteButtonClick(Sender: TObject);
procedure BindListClick(Sender: TObject);
procedure ClearButtonClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure HelpClick(Sender: TObject);
procedure IndexListChange(Sender: TObject);
private
FDataSet: TDataSet;
FMasterDataSet: TDataSet;
FDataSetProxy: TFieldLinkProperty;
FFullIndexName: string;
MasterFieldList: string;
IndexFieldList: string;
OrderedDetailList: TStringList;
OrderedMasterList: TStringList;
procedure OrderFieldList(OrderedList, List: TStrings);
procedure AddToBindList(const Str1, Str2: string);
procedure Initialize;
property FullIndexName: string read FFullIndexName;
procedure SetDataSet(Value: TDataSet);
public
property DataSet: TDataSet read FDataSet write SetDataSet;
property DataSetProxy: TFieldLinkProperty read FDataSetProxy write FDataSetProxy;
function Edit: Boolean;
end;
function EditMasterFields(ADataSet: TDataSet; ADataSetProxy: TFieldLinkProperty): Boolean;
implementation
{$R *.DFM}
uses Dialogs, DBConsts, LibHelp, TypInfo, DsnDBCst;
{ Utility Functions }
function StripFieldName(const Fields: string; var Pos: Integer): string;
var
I: Integer;
begin
I := Pos;
while (I <= Length(Fields)) and (Fields[I] <> ';') do Inc(I);
Result := Copy(Fields, Pos, I - Pos);
if (I <= Length(Fields)) and (Fields[I] = ';') then Inc(I);
Pos := I;
end;
function StripDetail(const Value: string): string;
var
S: string;
I: Integer;
begin
S := Value;
I := 0;
while Pos('->', S) > 0 do
begin
I := Pos('->', S);
S[I] := ' ';
end;
Result := Copy(Value, 0, I - 2);
end;
function StripMaster(const Value: string): string;
var
S: string;
I: Integer;
begin
S := Value;
I := 0;
while Pos('->', S) > 0 do
begin
I := Pos('->', S);
S[I] := ' ';
end;
Result := Copy(Value, I + 3, Length(Value));
end;
function EditMasterFields(ADataSet: TDataSet; ADataSetProxy: TFieldLinkProperty): Boolean;
begin
with TLinkFields.Create(nil) do
try
DataSetProxy := ADataSetProxy;
DataSet := ADataSet;
Result := Edit;
finally
Free;
end;
end;
{ TFieldLinkProperty }
function TFieldLinkProperty.GetIndexBased: Boolean;
begin
Result := False;
end;
function TFieldLinkProperty.GetIndexDefs: TIndexDefs;
begin
Result := nil;
end;
function TFieldLinkProperty.GetIndexFieldNames: string;
begin
Result := '';
end;
function TFieldLinkProperty.GetIndexName: string;
begin
Result := '';
end;
procedure TFieldLinkProperty.GetIndexNames(List: TStrings);
var
i: Integer;
begin
if IndexDefs <> nil then
for i := 0 to IndexDefs.Count - 1 do
if (ixPrimary in IndexDefs.Items[i].Options) and
(IndexDefs.Items[i].Name = '') then
List.Add(SPrimary) else
List.Add(IndexDefs.Items[i].Name);
end;
procedure TFieldLinkProperty.GetFieldNamesForIndex(List: TStrings);
begin
end;
procedure TFieldLinkProperty.SetIndexFieldNames(const Value: string);
begin
end;
procedure TFieldLinkProperty.SetIndexName(const Value: string);
begin
end;
function TFieldLinkProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paDialog];
end;
procedure TFieldLinkProperty.Edit;
begin
FChanged := EditMasterFields(DataSet, Self);
if FChanged then Modified;
end;
constructor TFieldLinkProperty.CreateWith(ADataSet: TDataSet);
begin
FDataSet := ADataSet;
end;
function TFieldLinkProperty.GetDataSet: TDataSet;
begin
if FDataSet = nil then
FDataSet := TDataSet(GetComponent(0));
Result := FDataSet;
end;
{ TLinkFields }
procedure TLinkFields.FormCreate(Sender: TObject);
begin
OrderedDetailList := TStringList.Create;
OrderedMasterList := TStringList.Create;
HelpContext := hcDFieldLinksDesign;
end;
procedure TLinkFields.FormDestroy(Sender: TObject);
begin
OrderedDetailList.Free;
OrderedMasterList.Free;
end;
function TLinkFields.Edit;
begin
Initialize;
if ShowModal = mrOK then
begin
if FullIndexName <> '' then
DataSetProxy.IndexName := FullIndexName else
DataSetProxy.IndexFieldNames := IndexFieldList;
DataSetProxy.MasterFields := MasterFieldList;
Result := True;
end
else
Result := False;
end;
procedure TLinkFields.SetDataSet(Value: TDataSet);
var
IndexDefs: TIndexDefs;
begin
Value.FieldDefs.Update;
IndexDefs := DataSetProxy.IndexDefs;
if Assigned(IndexDefs) then IndexDefs.Update;
if not Assigned(Value.DataSource) or not Assigned(Value.DataSource.DataSet) then
DatabaseError(SMissingDataSource, Value);
Value.DataSource.DataSet.FieldDefs.Update;
FDataSet := Value;
FMasterDataSet := Value.DataSource.DataSet;
end;
procedure TLinkFields.Initialize;
var
SIndexName: string;
procedure SetUpLists(const MasterFieldList, DetailFieldList: string);
var
I, J: Integer;
MasterFieldName, DetailFieldName: string;
begin
I := 1;
J := 1;
while (I <= Length(MasterFieldList)) and (J <= Length(DetailFieldList)) do
begin
MasterFieldName := StripFieldName(MasterFieldList, I);
DetailFieldName := StripFieldName(DetailFieldList, J);
if (MasterList.Items.IndexOf(MasterFieldName) <> -1) and
(OrderedDetailList.IndexOf(DetailFieldName) <> -1) then
begin
with OrderedDetailList do
Objects[IndexOf(DetailFieldName)] := TObject(True);
with DetailList.Items do Delete(IndexOf(DetailFieldName));
with MasterList.Items do Delete(IndexOf(MasterFieldName));
BindList.Items.Add(Format('%s -> %s',
[DetailFieldName, MasterFieldName]));
ClearButton.Enabled := True;
end;
end;
end;
begin
if not DataSetProxy.IndexBased then
begin
IndexLabel.Visible := False;
IndexList.Visible := False;
end
else with DataSetProxy do
begin
GetIndexNames(IndexList.Items);
if IndexFieldNames <> '' then
SIndexName := IndexDefs.FindIndexForFields(IndexFieldNames).Name
else SIndexName := IndexName;
if (SIndexName <> '') and (IndexList.Items.IndexOf(SIndexName) >= 0) then
IndexList.ItemIndex := IndexList.Items.IndexOf(SIndexName) else
IndexList.ItemIndex := 0;
end;
with DataSetProxy do
begin
MasterFieldList := MasterFields;
if (IndexFieldNames = '') and (IndexName <> '') and
(IndexDefs.IndexOf(IndexName) >=0) then
IndexFieldList := IndexDefs[IndexDefs.IndexOf(IndexName)].Fields else
IndexFieldList := IndexFieldNames;
end;
IndexListChange(nil);
FMasterDataSet.GetFieldNames(MasterList.Items);
OrderedMasterList.Assign(MasterList.Items);
SetUpLists(MasterFieldList, IndexFieldList);
end;
procedure TLinkFields.IndexListChange(Sender: TObject);
var
I: Integer;
IndexExp: string;
begin
DetailList.Items.Clear;
if DataSetProxy.IndexBased then
begin
DataSetProxy.IndexName := IndexList.Text;
I := DataSetProxy.IndexDefs.IndexOf(DataSetProxy.IndexName);
if (I <> -1) then IndexExp := DataSetProxy.IndexDefs.Items[I].Expression;
if IndexExp <> '' then
DetailList.Items.Add(IndexExp) else
DataSetProxy.GetFieldNamesForIndex(DetailList.Items);
end else
DataSet.GetFieldNames(DetailList.Items);
MasterList.Items.Assign(OrderedMasterList);
OrderedDetailList.Assign(DetailList.Items);
for I := 0 to OrderedDetailList.Count - 1 do
OrderedDetailList.Objects[I] := TObject(False);
BindList.Clear;
AddButton.Enabled := False;
ClearButton.Enabled := False;
DeleteButton.Enabled := False;
MasterList.ItemIndex := -1;
end;
procedure TLinkFields.OrderFieldList(OrderedList, List: TStrings);
var
I, J: Integer;
MinIndex, Index, FieldIndex: Integer;
begin
for J := 0 to List.Count - 1 do
begin
MinIndex := $7FFF;
FieldIndex := -1;
for I := J to List.Count - 1 do
begin
Index := OrderedList.IndexOf(List[I]);
if Index < MinIndex then
begin
MinIndex := Index;
FieldIndex := I;
end;
end;
List.Move(FieldIndex, J);
end;
end;
procedure TLinkFields.AddToBindList(const Str1, Str2: string);
var
I: Integer;
NewField: string;
NewIndex: Integer;
begin
NewIndex := OrderedDetailList.IndexOf(Str1);
NewField := Format('%s -> %s', [Str1, Str2]);
with BindList.Items do
begin
for I := 0 to Count - 1 do
begin
if OrderedDetailList.IndexOf(StripDetail(Strings[I])) > NewIndex then
begin
Insert(I, NewField);
Exit;
end;
end;
Add(NewField);
end;
end;
procedure TLinkFields.BindingListClick(Sender: TObject);
begin
AddButton.Enabled := (DetailList.ItemIndex <> LB_ERR) and
(MasterList.ItemIndex <> LB_ERR);
end;
procedure TLinkFields.AddButtonClick(Sender: TObject);
var
DetailIndex: Integer;
MasterIndex: Integer;
begin
DetailIndex := DetailList.ItemIndex;
MasterIndex := MasterList.ItemIndex;
AddToBindList(DetailList.Items[DetailIndex],
MasterList.Items[MasterIndex]);
with OrderedDetailList do
Objects[IndexOf(DetailList.Items[DetailIndex])] := TObject(True);
DetailList.Items.Delete(DetailIndex);
MasterList.Items.Delete(MasterIndex);
ClearButton.Enabled := True;
AddButton.Enabled := False;
end;
procedure TLinkFields.ClearButtonClick(Sender: TObject);
var
I: Integer;
BindValue: string;
begin
for I := 0 to BindList.Items.Count - 1 do
begin
BindValue := BindList.Items[I];
DetailList.Items.Add(StripDetail(BindValue));
MasterList.Items.Add(StripMaster(BindValue));
end;
BindList.Clear;
ClearButton.Enabled := False;
DeleteButton.Enabled := False;
OrderFieldList(OrderedDetailList, DetailList.Items);
DetailList.ItemIndex := -1;
MasterList.Items.Assign(OrderedMasterList);
for I := 0 to OrderedDetailList.Count - 1 do
OrderedDetailList.Objects[I] := TObject(False);
AddButton.Enabled := False;
end;
procedure TLinkFields.DeleteButtonClick(Sender: TObject);
var
I: Integer;
begin
with BindList do
begin
for I := Items.Count - 1 downto 0 do
begin
if Selected[I] then
begin
DetailList.Items.Add(StripDetail(Items[I]));
MasterList.Items.Add(StripMaster(Items[I]));
with OrderedDetailList do
Objects[IndexOf(StripDetail(Items[I]))] := TObject(False);
Items.Delete(I);
end;
end;
if Items.Count > 0 then Selected[0] := True;
DeleteButton.Enabled := Items.Count > 0;
ClearButton.Enabled := Items.Count > 0;
OrderFieldList(OrderedDetailList, DetailList.Items);
DetailList.ItemIndex := -1;
OrderFieldList(OrderedMasterList, MasterList.Items);
MasterList.ItemIndex := -1;
AddButton.Enabled := False;
end;
end;
procedure TLinkFields.BindListClick(Sender: TObject);
begin
DeleteButton.Enabled := BindList.ItemIndex <> LB_ERR;
end;
procedure TLinkFields.BitBtn1Click(Sender: TObject);
var
Gap: Boolean;
I: Integer;
FirstIndex: Integer;
begin
FirstIndex := -1;
MasterFieldList := '';
IndexFieldList := '';
FFullIndexName := '';
if DataSetProxy.IndexBased then
begin
Gap := False;
for I := 0 to OrderedDetailList.Count - 1 do
begin
if Boolean(OrderedDetailList.Objects[I]) then
begin
if Gap then
begin
MessageDlg(Format(SLinkDesigner,
[OrderedDetailList[FirstIndex]]), mtError, [mbOK], 0);
ModalResult := 0;
DetailList.ItemIndex := DetailList.Items.IndexOf(OrderedDetailList[FirstIndex]);
Exit;
end;
end
else begin
Gap := True;
if FirstIndex = -1 then FirstIndex := I;
end;
end;
if not Gap then FFullIndexName := DataSetProxy.IndexName;
end;
with BindList do
begin
for I := 0 to Items.Count - 1 do
begin
MasterFieldList := Format('%s%s;', [MasterFieldList, StripMaster(Items[I])]);
IndexFieldList := Format('%s%s;', [IndexFieldList, StripDetail(Items[I])]);
end;
if MasterFieldList <> '' then
SetLength(MasterFieldList, Length(MasterFieldList) - 1);
if IndexFieldList <> '' then
SetLength(IndexFieldList, Length(IndexFieldList) - 1);
end;
end;
procedure TLinkFields.HelpClick(Sender: TObject);
begin
Application.HelpContext(HelpContext);
end;
end.